/**
 * Copyright 2011-2011 - Members of the Chaupal Community
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */


package net.chaupal.Impl.Serialization;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import net.chaupal.Impl.Tools.Soundness;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class Serializer {

    // Log

    private static final Logger LOG = LoggerFactory.getLogger(Serializer.class);

    /**
     * Serializes the provided object into a byte array[].
     *
     * <p>This method returns <tt>null</tt> if the provided parameter is
     * <tt>null</tt>.
     *
     * @param inObject the object to serialize
     * @return a byte array
     * @throws IOException if object cannot be serialized 
     */
    public static byte[] serializeToByteArray(Object inObject)
            throws IOException {

        // Sanity check
        if ( inObject == null ) return null;

        final ByteArrayOutputStream TmpBAOS = new ByteArrayOutputStream();
        ObjectOutputStream TmpOOS = null;

        TmpOOS = new ObjectOutputStream(TmpBAOS);
        TmpOOS.writeObject(inObject);
        TmpOOS.close();

        return TmpBAOS.toByteArray();

    }

    /**
     * Unserializes the provided byte array[] into an Object.
     *
     * <p>This method returns <tt>null</tt> if the provided parameter is
     * <tt>null</tt>.
     *
     * <p>If an issue is encountered, a severe LOG entry is create and
     * the method throws an {@code IllegalArgumentException}.
     *
     * @param <T> return type
     * @param inBA the byte array to unserialize
     * @return an object instance
     */
    @SuppressWarnings("unchecked")
    public static <T> T unserializeToObject(byte[] inBA) {

        // Sanity 
        if ( inBA == null ) return null;
            
        return (T) unserializeToObject(inBA, 0, inBA.length);

    }

    /**
     * Unserializes the provided byte array[] into an Object.
     *
     * <p>This method returns <tt>null</tt> if the provided parameter is
     * <tt>null</tt>.
     *
     * <p>If an issue is encountered, a severe LOG entry is create and
     * the method throws an {@code IllegalArgumentException}.
     *
     * @param <T> return type
     * @param inBA the byte array to unserialize
     * @param start start position in the byte array
     * @param length number of byte to read
     * @return an object instance
     */
    @SuppressWarnings("unchecked")
    public static <T> T unserializeToObject(
            byte[] inBA, int start, int length) {
    
        // Sanity check
        if ( inBA == null ) return null;

        final ByteArrayInputStream TmpBAIS
                = new ByteArrayInputStream(inBA, start, length);
        ObjectInputStream TmpOIS = null;

        Object Result = null;
        
        try {
            TmpOIS = new ObjectInputStream(TmpBAIS);
            Result = TmpOIS.readObject();
            TmpOIS.close();
        } catch (IOException ex) {
            Soundness.unreachableCodeReached(LOG, ex);
        } catch (ClassNotFoundException ex) {
            Soundness.unreachableCodeReached(LOG, ex);
        }

        return (T) Result;

    }

}
